package GA.tournaments;

import LUDOSimulator.LUDOPlayer;
import LUDOSimulator.PlayerResult;

public class ExtendedPlayerResult extends PlayerResult implements Comparable<ExtendedPlayerResult>
{
	protected int losses = 0;
	protected int secondWorst = 0;
	protected int secondBest = 0;
	protected int maxPointValue = 0;
	private final int maxPointPrRound = 3+2+1+0;
	
	/**
	 * Player result with some special features.
	 * @param l - LUDOPlayer
	 */
	public ExtendedPlayerResult(LUDOPlayer l)
	{
		super(l, 0, 0);
		//super(l,null,0,0,0);
	}
	
	/**
	 * Player result with some special features.
	 * @param l - LUDOPlayer
	 * @param n - Number of the LUDOPlayer in a list
	 */
	public ExtendedPlayerResult(LUDOPlayer l, int n)
	{
		super(l, n, 0, 0, 0);
	}
	
	/**
	 * <i><b>ExtendedPlayerResult special feature</b></i>.<p>
	 * Returning how many times the LUDOPlayer has been on second place.
	 * @return Integer that is always zero or higher
	 */
	public int getSecondPlace()
	{
		return secondBest;
	}
	
	/**
	 * <i><b>ExtendedPlayerResult special feature</b></i>.<p>
	 * Returning how many times the LUDOPlayer has been on third place.
	 * @return Integer that is always zero or higher
	 */
	public int getThirdPlace()
	{
		return secondWorst;
	}
	
	/**
	 * <i><b>ExtendedPlayerResult special feature</b></i>.<p>
	 * Returning how many times the LUDOPlayer has been on fourth place.<p>
	 * In other words. How many times it has lost a game.
	 * @return Integer that is always zero or higher
	 */
	public int getLosses()
	{
		return losses;
	}
	
	/**
	 * <i><b>ExtendedPlayerResult special feature</b></i>.<p>
	 * Adds the results along the ways as the game is played.
	 * @param r - The result given from LUDOBoard
	 */
	public void add(int r)
	{
		switch(r)
		{
			case 0:
				losses++;
				break;
			case 1:
				secondWorst++;
				break;
			case 2:
				secondBest++;
				break;
			case 3:
				wins++;
				break;
			default:
				return;
		}
		games++;
		result += r;
		maxPointValue += maxPointPrRound;
		refresh = true;
	}

	
	private enum COMPARER { RES_WIN_SEC_THI_LOS, LOS_RES_WIN_SEC_THI, WIN_LOS_RES_SEC_THI, WINLOS_RATIO_WIN_SEC,
							RESMAX_RATIO_WIN_SEC, WINGAM_RATIO, RESMAX_WINGAM_RATIO}; //TODO Win/loss ratio in contrast of results
							
	private static COMPARER to = COMPARER.RES_WIN_SEC_THI_LOS;

	
	
	private double thisresmax = -1;
	private double oresmax 	  = -1;
	private double thiswinlos = -1;
	private double owinlos    = -1;
	private double thiswingam = -1;
	private double owingam    = -1;
	private boolean refresh   = true;
	
	/**
	 * <i><b>ExtendedPlayerResult special feature</b></i>.<p>
	 */
	public int compareTo(ExtendedPlayerResult o) 
	{
		if(!refresh)
		{
			thisresmax = (this.result*100)/this.maxPointValue;
			thiswinlos = this.losses == 0 ? (this.wins * 100) / 0.1 : (this.wins * 100) / this.losses;
			thiswingam = (this.wins*100)/this.games;
			refresh = false;
		}
		
		oresmax = o.maxPointValue == 0 ? 0 : (o.result*100)/o.maxPointValue;
		owinlos = o.losses == 0 ? (o.wins * 100) / 0.1 : (o.wins * 100) / o.losses;
		owingam = o.games == 0 ? 0 : (o.wins*100)/o.games;
		switch(to)
		{
			case RESMAX_WINGAM_RATIO:
				return	thisresmax == oresmax ?
							thiswingam == owingam ?
								0
							: thiswingam > owingam ? -1 : 1
						: thisresmax > oresmax ? -1 : 1;
						
			case WINGAM_RATIO:
				return 	thiswingam == owingam ?
							0
						: thiswingam > owingam ? -1 : 1;
						
			case RESMAX_RATIO_WIN_SEC:
				return 	thisresmax == oresmax ?
							this.wins == o.wins ?
								this.secondBest == o.secondBest ?
									0
								: this.secondBest > o.secondBest ? -1 : 1
							:this.wins > o.wins ? -1 : 1
						: thisresmax > oresmax ? -1 : 1;
						
			case WINLOS_RATIO_WIN_SEC:
				return 	thiswinlos == owinlos ?
							this.wins == o.wins ?
								this.secondBest == o.secondBest ?
									0
								: this.secondBest > o.secondBest ? -1 : 1
							: this.wins > o.wins ? -1 : 1
						: thiswinlos > owinlos ? -1 : 1;
						
			case RES_WIN_SEC_THI_LOS:
				return 	this.result==o.result ? 
							this.wins == o.wins ?
								this.secondBest == o.secondBest ?
									this.secondWorst == o.secondWorst ?
										this.losses == o.losses ? 
											0 
										: this.losses > o.losses ? 1 : -1
									: this.secondWorst > o.secondWorst ? 1 : -1
								: this.secondBest > o.secondBest ? -1 : 1
							: this.wins > o.wins ? -1 : 1
					    : this.result > o.result ? -1 : 1;
					    
			case LOS_RES_WIN_SEC_THI:
				return 	this.losses == o.losses ?
							this.result==o.result ?
								this.wins == o.wins ?
									this.secondBest == o.secondBest ?
										this.secondWorst == o.secondWorst ?
											0 
										: this.secondWorst > o.secondWorst ? 1 : -1
									: this.secondBest > o.secondBest ? -1 : 1
								: this.wins > o.wins ? -1 : 1
						    : this.result > o.result ? -1 : 1
						: this.losses > o.losses ? 1 : -1;
					    
			case WIN_LOS_RES_SEC_THI:
				return 	this.wins == o.wins ?
							this.losses == o.losses ? 
								this.result==o.result ?
									this.secondBest == o.secondBest ?
										this.secondWorst == o.secondWorst ?
											0 
										: this.secondWorst > o.secondWorst ? 1 : -1
									: this.secondBest > o.secondBest ? -1 : 1
								: this.result > o.result ? -1 : 1
							: this.losses > o.losses ? 1 : -1
						: this.wins > o.wins ? -1 : 1;
			default:
				return 0;
		}
	}

}
